using System;
using System.Linq.Expressions;
using Moq;
using NUnit.Framework;
using Tycho.Parser.Peg;

namespace Tycho.Parser.Tests.Peg {
    [TestFixture]
    public class SpecialKeywordBuilderSpecification {
        [Test]
        public void ShouldCreateBeginBlockIfOpenBrace () {
            AssertFactoryCreateForKeyword ("{", f => f.CreateBeginBlock());
        }

        [Test]
        public void ShouldCreateEndBlockIfCloseBrace () {
            AssertFactoryCreateForKeyword ("}", f => f.CreateEndBlock());
        }

        [Test]
        public void ShouldCreateStatementDelimiterIfSemiColon () {
            AssertFactoryCreateForKeyword (";", f => f.CreateStatementDelimiter());
        }

        [Test]
        public void ShouldCreateIdentifierKeywordIfIdentifier () {
            AssertFactoryCreateForKeyword ("abc-def", f => f.CreateIdentifierKeyword ("abc-def"));
        }

        [Test]
        public void ShouldCreateOperatorKeywordIfOperator () {
            AssertFactoryCreateForKeyword ("$%^", f => f.CreateOperatorKeyword ("$%^"));
        }

        [Test]
        public void ShouldCreatePunctuationIfAnythingElse () {
            AssertFactoryCreateForKeyword ("so called comma", f => f.CreatePunctuation ("so called comma"));
        }

        [Test]
        public void ShouldCreateInrementingPunctuationIfOpenBracketOrOpenParen () {
            AssertFactoryCreateForKeyword ("(", f => f.CreateIncrementingPunctuation ("("));
            AssertFactoryCreateForKeyword ("[", f => f.CreateIncrementingPunctuation ("["));
        }

        [Test]
        public void ShouldCreateDerementingPunctuationIfCloseBracketOrCloseParen () {
            AssertFactoryCreateForKeyword (")", f => f.CreateDecrementingPunctuation (")"));
            AssertFactoryCreateForKeyword ("]", f => f.CreateDecrementingPunctuation ("]"));
        }

        private static void AssertFactoryCreateForKeyword (string keyword, Expression<Func<ISpecialKeywordProductionFactory, IProduction>> factoryCreateExpression) {
            var factory = new Mock<ISpecialKeywordProductionFactory> ();
            var production = new Mock<IProduction> ().Object;
            factory.Setup (factoryCreateExpression).Returns (production);

            var builder = new SpecialKeywordBuilder (factory.Object);
            Assert.That (builder.Build (keyword), Is.SameAs (production));
        }
    }
}